package com.example.gateway.filter;

import com.example.common.dto.Result;
import com.example.common.exception.BusinessException;
import com.example.common.security.JwtUtils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.ArrayList;
import java.util.List;

/**
 * 鉴权过滤器
 *
 * @author cui haida
 * @version JDK 8
 * 2025/8/5
 */
@Component
public class AuthFilter implements GlobalFilter, Ordered {

    /**
     * 白名单
     */
    private static final List<String> WHITE_LIST = new ArrayList<>();
    static {
        WHITE_LIST.add("/auth/login");
        WHITE_LIST.add("/auth/register");
    }

    public JwtUtils jwtUtils;

    private final ObjectMapper objectMapper;

    public AuthFilter(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }


    /**
     * 鉴权过滤器
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 获取请求及其路径
        ServerHttpRequest request = exchange.getRequest();
        String path = request.getPath().value();

        // 白名单放行
        if (isWhiteList(path)) {
            return chain.filter(exchange);
        }
        // 获取到token
        String token = getTokenFromHeader(request);

        // 如果没有拿到，直接返回未授权的响应
        if (token == null) {
            return unauthorizedResponse(exchange, "缺少认证信息");
        }

        try {
            String username = jwtUtils.getUsernameFromToken(token);

            // 添加用户信息到header
            ServerHttpRequest modifiedRequest = request.mutate()
                    .header("X-User-Id", username)
                    .build();
            // 继续处理请求
            return chain.filter(exchange.mutate().request(modifiedRequest).build());
        } catch (BusinessException e) {
            return unauthorizedResponse(exchange, e.getMessage());
        } catch (Exception e) {
            return unauthorizedResponse(exchange, "无效的认证信息");
        }
    }

    /**
     * 判断是否是白名单
     */
    private boolean isWhiteList(String path) {
        return WHITE_LIST.stream().anyMatch(path::startsWith);
    }

    /**
     * 从header中获取token
     */
    private String getTokenFromHeader(ServerHttpRequest request) {
        String header = request.getHeaders().getFirst(HttpHeaders.AUTHORIZATION);
        if (header != null && header.startsWith("Bearer ")) {
            return header.substring(7);
        }
        return null;
    }

    /**
     * 响应未授权
     * 鉴权失败的时候返回什么
     */
    private Mono<Void> unauthorizedResponse(ServerWebExchange exchange, String message) {
        ServerHttpResponse response = exchange.getResponse();
        response.setStatusCode(HttpStatus.UNAUTHORIZED);
        response.getHeaders().setContentType(MediaType.APPLICATION_JSON);

        Result<?> result = Result.unauthorized(message);
        try {
            byte[] bytes = objectMapper.writeValueAsBytes(result);
            DataBuffer buffer = response.bufferFactory().wrap(bytes);
            return response.writeWith(Mono.just(buffer));
        } catch (JsonProcessingException e) {
            return response.setComplete();
        }
    }

    @Override
    public int getOrder() {
        return -100;
    }
}